﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;

namespace E.Story
{
    /// <summary>
    /// 故事视图元素
    /// </summary>
    public class StoryGraphView : GraphView
    {
        #region UI元素

        private StoryEditorWindow storyEditorWindow;
        private NodeCreationBox nodeCreationBox;
        private NavMap navMap;
        private VarPanel varPanel;
        private Label lblVarCount;
        private Label lblNodeCount;
        private Label lblGroupCount;
        private Label lblNoteCount;
        private Label lblScale;
        //private Label lblMousePosition;

        public VarPanel VarPanel { get => varPanel; }

        #endregion


        #region 标题重复相关变量

        private SerializableDictionary<string, NodeErrorData> duplicateUngroupedNodesRecord;
        private SerializableDictionary<string, GroupErrorData> duplicateGroupsRecord;
        private SerializableDictionary<Group, SerializableDictionary<string, NodeErrorData>> duplicateGroupedNodesRecord;
        private int duplicateTitlesAmount;

        public int DuplicateTitlesAmount { get => duplicateTitlesAmount; set => duplicateTitlesAmount = value; }

        #endregion


        #region 当前视图元素

        public List<BaseGroup> Groups 
        { 
            get
            {
                // 遍历获取元素
                List<BaseGroup> groups = new();
                graphElements.ForEach(element =>
                {
                    if (element is BaseGroup group)
                    {
                        groups.Add(group);
                        return;
                    }
                });
                return groups;
            }
        }

        public List<BaseNode> Nodes 
        { 
            get
            {
                // 遍历获取元素
                List<BaseNode> baseNodes = new();
                nodes.ForEach(element =>
                {
                    if (element is BaseNode node)
                    {
                        baseNodes.Add(node);
                        return;
                    }
                });
                return baseNodes;
            }
        }

        public List<VarData> Vars 
        {
            get => varPanel.VarDatas;
        }

        public List<BaseNote> Notes
        { 
            get
            {
                // 遍历获取元素
                List<BaseNote> notes = new();
                graphElements.ForEach(element =>
                {
                    if (element is BaseNote note)
                    {
                        notes.Add(note);
                        return;
                    }
                });
                return notes;
            }
        }

        #endregion


        #region 重写方法

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="window">编辑器窗口</param>
        public StoryGraphView(StoryEditorWindow window)
        {
            // 关联窗口类
            storyEditorWindow = window;

            // 初始化变量
            duplicateUngroupedNodesRecord = new();
            duplicateGroupsRecord = new();
            duplicateGroupedNodesRecord = new();

            // 添加小组件
            AddGridBackground();
            AddManipulators();
            AddNodeCreationBox();
            AddNavMap();
            AddVarPanel();
            AddStoryInfo();

            // 定义事件回调方法
            OnOpenNodeCreationBox();
            OnElementsReadyDelete();
            OnGroupElementsAdded();
            OnGroupElementsRemoved();
            OnGroupRenamed();
            OnGraphViewChanged();
            OnSetCanPaste();
            OnCopyElements();
            OnPasteElements();
            OnViewTransformChanged();

            // 添加默认数据
            AddDefaultNodes();
            AddDefaultVarData();
        }

        /// <summary>
        /// 获取可连上的节点接口
        /// </summary>
        /// <param name="startPort">开始节点</param>
        /// <param name="nodeAdapter">节点适配器</param>
        /// <returns>节点列表</returns>
        public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
        {
            // 获取所有端口
            List<Port> result = ports.ToList();
            // 执行筛选
            result = result.Where
            (
                           // 两个端口的逻辑方向不能相同（即数据流向输入输出不能相同）
                endport => endport.direction != startPort.direction
                           // 两个端口不能为同一个端口
                           && endport.node != startPort.node
            ).ToList();

            return result;
        }

        /// <summary>
        /// 构建右键菜单
        /// </summary>
        /// <param name="evt"></param>
        public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
        {
            // 添加操作
            if (evt.target is GraphView || evt.target is Edge)
            {
                VisualElement temp = (VisualElement)evt.target;
                evt.menu.AppendAction("添加节点        Space", action =>
                {
                    // 获取光标当前屏幕位置
                    Vector2 screenMousePosition = action.eventInfo.mousePosition + storyEditorWindow.position.position + new Vector2(50, 35);
                    // 触发请求事件
                    nodeCreationRequest(new NodeCreationContext
                    {
                        screenMousePosition = screenMousePosition,
                        target = temp,
                        index = -1
                    });
                });
            }
            if (evt.target is GraphView || evt.target is Node)
            {
                evt.menu.AppendAction("添加分组", action =>
                {
                    CreateGroup("分组", GetLocalMousePosition(action.eventInfo.localMousePosition));
                });
            }
            if (evt.target is GraphView)
            {
                evt.menu.AppendAction("添加便签", action =>
                {
                    CreateNote("新便签", "", new Rect(GetLocalMousePosition(action.eventInfo.localMousePosition), new Vector2(200, 200)));
                });
            }

            evt.menu.AppendSeparator();

            //对象操作
            if (evt.target is GraphView || evt.target is Node || evt.target is Group)
            {
                evt.menu.AppendAction("剪切        Ctrl+X", delegate
                {
                    CutSelectionCallback();
                }, canCutSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            if (evt.target is GraphView || evt.target is Node || evt.target is Group)
            {
                evt.menu.AppendAction("复制        Ctrl+C", delegate
                {
                    CopySelectionCallback();
                }, canCopySelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            if (evt.target is GraphView)
            {
                evt.menu.AppendAction("粘贴        Ctrl+V", delegate
                {
                    PasteCallback();
                }, canPaste ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            if (evt.target is GraphView || evt.target is Node || evt.target is Group)
            {
                evt.menu.AppendAction("拷贝        Ctrl+D", delegate
                {
                    DuplicateSelectionCallback();
                }, canDuplicateSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            evt.menu.AppendSeparator();
            if (evt.target is GraphView || evt.target is Node || evt.target is Group || evt.target is Edge)
            {
                evt.menu.AppendAction("删除        Delete", delegate
                {
                    DeleteSelectionCallback(AskUser.DontAskUser);
                }, canDeleteSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }

            evt.menu.AppendSeparator();

            // 视图操作
            evt.menu.AppendAction("聚焦上一个        [", delegate
            {
                FramePrev();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("聚焦下一个        ]", delegate
            {
                FrameNext();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("聚焦选中        F", delegate
            {
                FrameSelection();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("聚焦全部        A", delegate
            {
                FrameAll();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("还原视图        O", delegate
            {
                FrameOrigin();
            }, DropdownMenuAction.Status.Normal);
        }

        #endregion

        
        #region 回调方法

        /// <summary>
        /// 当打开添加节点对话框时
        /// </summary>
        private void OnOpenNodeCreationBox()
        {
            nodeCreationRequest = context =>
            {
                // 指定相关联的对象
                nodeCreationBox.SetVisualElement(context.target);

                // 打开搜索框
                SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), nodeCreationBox);
            };
        }

        /// <summary>
        /// 当元素准备删除时
        /// </summary>
        private void OnElementsReadyDelete()
        {
            // 在此处对选中的元素进行过滤
            deleteSelection = (operationName, askUser) =>
            {
                List<ISelectable> readyToDelete = new();

                // 遍历当前选中目标
                foreach (GraphElement element in selection)
                {
                    // 如果是节点
                    if (element is BaseNode node)
                    {
                        // 过滤掉开始节点
                        if (node is StartNode)
                        {
                            string str = "不可以删除开始节点。";
                            EditorUtility.DisplayDialog("警告", str, "明白");
                            continue;
                        }

                        // 过滤掉最后一个结束节点
                        if (node is EndNode)
                        {
                            if (GetEndNodesAmount() == 1)
                            {
                                string str = "不可以删除最后一个结束节点。";
                                EditorUtility.DisplayDialog("警告", str, "明白");
                                continue;
                            }
                        }

                        // 加入待删除列表
                        readyToDelete.Add(node);
                    }
                    // 如果是连线
                    else if (element is Edge edge)
                    {
                        readyToDelete.Add(edge);
                    }
                    // 如果是分组
                    else if (element is BaseGroup group)
                    {
                        readyToDelete.Add(group);
                    }
                    // 如果是便签
                    else if (element is BaseNote note)
                    {
                        readyToDelete.Add(note);
                    }
                }

                // 更新选中目标
                selection = readyToDelete;
                // 执行删除
                DeleteSelection();
            };
        }

        /// <summary>
        /// 当往分组里加入节点时
        /// </summary>
        private void OnGroupElementsAdded()
        {
            elementsAddedToGroup = (group, elements) =>
            {
                BaseGroup baseGroup = (BaseGroup)group;
                foreach (GraphElement element in elements)
                {
                    // 如果添加的是节点
                    if (element is BaseNode node)
                    {
                        // 记录节点所属分组
                        node.Group = baseGroup;
                        //Debug.Log("节点【" + node.Title + "】已加入【" + baseGroup.title + "】");

                        // 检测是否允许标题重复
                        if (!StoryEditorWindow.AllowDuplicateTitles)
                        {
                            // 更新字典
                            RemoveDuplicateUngroupedNodeRecord(node);
                            AddDuplicateGroupedNodeRecord(node, baseGroup);
                        }
                    }
                }
            };
        }

        /// <summary>
        /// 当从分组里移出节点时
        /// </summary>
        private void OnGroupElementsRemoved()
        {
            elementsRemovedFromGroup = (group, elements) =>
            {
                BaseGroup baseGroup = (BaseGroup)group;
                foreach (GraphElement element in elements)
                {
                    // 如果添加的是节点
                    if (element is BaseNode node)
                    {
                        // 清除分组信息
                        node.Group = null;
                        //Debug.Log("节点【" + node.Title + "】已移出【" + baseGroup.title + "】");

                        // 检测是否允许标题重复
                        if (!StoryEditorWindow.AllowDuplicateTitles)
                        {
                            // 更新字典
                            RemoveDuplicateGroupedNodeRecord(node, baseGroup);
                            AddDuplicateUngroupedNodeRecord(node);
                        }
                    }
                }
            };
        }

        /// <summary>
        /// 当重命名分组时
        /// </summary>
        private void OnGroupRenamed()
        {
            groupTitleChanged = (group, newTitle) =>
            {
                BaseGroup baseGroup = (BaseGroup)group;

                // 清除无效字符
                string temp = newTitle;
                if (!StoryEditorWindow.AllowWhitespacesInTitles)
                {
                    temp = temp.RemoveWhitespaces();
                }
                if (!StoryEditorWindow.AllowSpecialCharactersInTitles)
                {
                    temp = temp.RemoveSpecialCharacters();
                }
                baseGroup.title = temp;

                // 检测是否允许标题重复
                if (StoryEditorWindow.AllowDuplicateTitles)
                {
                    // 更新标题
                    baseGroup.OldTitle = temp;
                }
                else
                {
                    RemoveDuplicateGroupRecord(baseGroup);
                    baseGroup.OldTitle = temp;
                    AddDuplicateGroupRecord(baseGroup);
                }
            };
        }

        /// <summary>
        /// 当视图发生变化
        /// </summary>
        private void OnGraphViewChanged()
        {
            // 定义事件
            graphViewChanged = (changes) =>
            {
                // 当即将创建连线时
                if (changes.edgesToCreate != null)
                {
                    // 遍历所有创建的连线
                    foreach (Edge edge in changes.edgesToCreate)
                    {
                        OnCreateEdge(edge);
                    }
                }

                // 当即将删除元素时
                if (changes.elementsToRemove != null)
                {
                    // 获取开始节点
                    GraphElement startNodes = changes.elementsToRemove.FirstOrDefault(n => n is StartNode);
                    // 将其移出删除列表
                    changes.elementsToRemove.Remove(startNodes);

                    // 获取结束节点列表
                    List<GraphElement> endNodes = changes.elementsToRemove.Where(n => n is EndNode).ToList();
                    // 如果与视图中所有结束节点的总数相同
                    if (endNodes.Count == GetEndNodesAmount())
                    {
                        // 获取最后一个结束节点
                        GraphElement lastEndNode = endNodes[^1];
                        // 将其移出删除列表
                        changes.elementsToRemove.Remove(lastEndNode);
                    }

                    // 遍历所有元素，执行对应事件
                    foreach (GraphElement element in changes.elementsToRemove)
                    {
                        // 如果是节点
                        if (element is BaseNode node)
                        {
                            OnDeleteNode(node);
                        }
                        // 如果是连线
                        else if (element is Edge edge)
                        {
                            OnDeleteEdge(edge);
                        }
                        // 如果是节点
                        else if (element is BaseGroup group)
                        {
                            OnDeleteGroup(group);
                        }
                        // 如果是便签
                        else if (element is BaseNote note)
                        {
                            OnDeleteNote(note);
                        }
                    }
                }

                // 当有元素移动后
                if (changes.movedElements != null)
                {
                    //Debug.Log(changes.moveDelta);
                }

                return changes;
            };
        }

        /// <summary>
        /// 当设置是否可粘贴
        /// </summary>
        private void OnSetCanPaste()
        {
            //canPasteSerializedData = (data) =>
            //{
            //    return data != "data";
            //};
        }

        /// <summary>
        /// 当复制元素时
        /// </summary>
        private void OnCopyElements()
        {
            serializeGraphElements = (elements) =>
            {
                CopyDatas copyDatas = new();
                foreach (GraphElement element in elements)
                {
                    // 检测是否节点
                    if (element is BaseNode node)
                    {
                        // 过滤掉开始节点
                        if (node.Type == NodeType.Start)
                        {
                            continue;
                        }

                        NodeData nodeData = node.GetNodeData();
                        copyDatas.nodeDatas.Add(nodeData);
                    }
                    // 检测是否分组
                    else if (element is BaseGroup group)
                    {
                        GroupData groupData = group.GetGroupData();
                        copyDatas.groupDatas.Add(groupData);
                    }
                    // 检测是否便签
                    else if (element is BaseNote note)
                    {
                        NoteData noteData = note.GetNoteData();
                        copyDatas.noteDatas.Add(noteData);
                    }
                }

                // 序列化成字符串
                string temp = JsonUtility.ToJson(copyDatas, true);
                //Debug.Log(temp);
                return temp;
            };
        }

        /// <summary>
        /// 当粘贴元素时
        /// </summary>
        private void OnPasteElements()
        {
            unserializeAndPaste = (operationName, data) =>
            {
                ClearSelection();

                // 将字符串反序列化
                CopyDatas copyDatas = JsonUtility.FromJson<CopyDatas>(data);

                // 创建字典，使新元素与旧ID匹配
                Dictionary<GroupData, BaseGroup> pasteGroups = new();
                Dictionary<NodeData, BaseNode> pasteNodes = new();

                // 遍历所有分组数据，创建分组
                foreach (GroupData groupData in copyDatas.groupDatas)
                {
                    // 更新节点标题
                    string newTitle = groupData.Title;
                    // 偏移节点位置
                    Vector2 newPosition = groupData.Position + new Vector2(50, 50);

                    // 创建节点
                    BaseGroup group = CreateGroup(newTitle, newPosition, false);
                    // 加入字典
                    pasteGroups.Add(groupData, group);
                }

                // 遍历所有节点数据，创建节点
                foreach (NodeData nodeData in copyDatas.nodeDatas)
                {
                    // 更新节点标题
                    string newTitle = nodeData.Title;
                    // 偏移节点位置
                    Vector2 newPosition = nodeData.Position + new Vector2(50, 50);

                    // 创建节点
                    BaseNode node = CreateNode(newTitle, nodeData.Type, newPosition, null, false);

                    // 加入字典
                    pasteNodes.Add(nodeData, node);

                    // 复制节点信息
                    node.Note = nodeData.Note;
                    node.ChoiceDatas = DataUtility.CloneChoiceDatas(nodeData.ChoiceDatas);

                    // 检测节点类型并获取特定变量值
                    if (node.Type == NodeType.Dialogue)
                    {
                        DialogueNode dNode = node as DialogueNode;
                        dNode.RoleName = nodeData.RoleName;
                        dNode.Portrait = nodeData.Portrait;
                        dNode.SentenceDatas = DataUtility.CloneSentenceDatas(nodeData.SentenceDatas);
                    }
                    else if (node.Type == NodeType.BGI)
                    {
                        BGINode bNode = node as BGINode;
                        bNode.BGI = nodeData.BGI;
                    }
                    else if (node.Type == NodeType.EditVar)
                    {
                        EditVarNode evNode = node as EditVarNode;
                        evNode.EditVarDatas = DataUtility.CloneEditVarDatas(nodeData.EditVarDatas);
                    }

                    // 绘制节点
                    node.Draw();
                }

                // 遍历所有节点
                foreach (KeyValuePair<NodeData, BaseNode> pasteNode in pasteNodes)
                {
                    NodeData nodeData = pasteNode.Key;
                    BaseNode node = pasteNode.Value;

                    // 更新分组信息
                    if (!string.IsNullOrEmpty(nodeData.GroupID))
                    {
                        foreach (GroupData id in pasteGroups.Keys)
                        {
                            if (nodeData.GroupID == id.GUID)
                            {
                                pasteGroups[id].AddElement(node);
                                node.Title = nodeData.Title;
                                break;
                            }
                        }
                    }

                    // 创建连线
                    foreach (Port outputPort in node.outputContainer.Children())
                    {
                        ChoiceData choiceData = (ChoiceData)outputPort.userData;

                        if (string.IsNullOrEmpty(choiceData.NextNodeID))
                        {
                            continue;
                        }

                        // 获取下个节点的数据
                        NodeData nextNodeData = pasteNodes.Keys.FirstOrDefault(x => x.GUID == choiceData.NextNodeID);

                        if (nextNodeData == null)
                        {
                            choiceData.NextNodeID = "";
                            continue;
                        }

                        // 获取下个节点的输入端口
                        BaseNode nextNode = pasteNodes[nextNodeData];
                        Port nextNodeInputPort = (Port)nextNode.inputContainer.Children().First();

                        // 记录GUID
                        choiceData.NextNodeID = nextNode.GUID;

                        // 创建连线
                        CreateEdge(outputPort, nextNodeInputPort);
                    }
                    node.RefreshPorts();
                }

                // 遍历所有便签数据，创建便签
                foreach (NoteData noteData in copyDatas.noteDatas)
                {
                    // 偏移位置
                    Vector2 newPosition = noteData.Layout.position + new Vector2(50, 50);
                    // 创建节点
                    BaseNote note = CreateNote(noteData.Title, noteData.Content, new Rect(newPosition, noteData.Layout.size));
                }
            };
        }

        /// <summary>
        /// 当视图变换时
        /// </summary>
        private void OnViewTransformChanged()
        {
            viewTransformChanged = (graphView) =>
            {
                //UpdateScaleInfo();
            };
        }

        #endregion


        #region 添加小组件

        /// <summary>
        /// 添加网格背景
        /// </summary>
        private void AddGridBackground()
        {
            GridBackground gridBackground = new();
            gridBackground.StretchToParentSize();
            Insert(0, gridBackground);
        }

        /// <summary>
        /// 添加视图操作组件
        /// </summary>
        private void AddManipulators()
        {
            // 添加视图缩放组件
            //this.AddManipulator(new ContentZoomer());    // 默认是0.25~1的缩放范围
            SetupZoom(0.2f, 2.0f);      // 自定义缩放范围
            // 添加视图拖拽组件
            this.AddManipulator(new ContentDragger());
            // 添加选中对象拖拽组件
            this.AddManipulator(new SelectionDragger());
            // 添加框选组件
            this.AddManipulator(new RectangleSelector());
        }

        /// <summary>
        /// 添加添加节点对话框
        /// </summary>
        private void AddNodeCreationBox()
        {
            nodeCreationBox = ScriptableObject.CreateInstance<NodeCreationBox>();
            nodeCreationBox.Init(this);
        }

        /// <summary>
        /// 添加导航地图
        /// </summary>
        private void AddNavMap()
        {
            navMap = new();
            navMap.Init();
            navMap.SetPosition(new(0, 0, 200, 200));

            Add(navMap);
        }

        /// <summary>
        /// 添加小黑板
        /// </summary>
        private void AddVarPanel()
        {
            varPanel = new();
            varPanel.Init(this);
            varPanel.Draw();

            Add(varPanel);
        }

        /// <summary>
        /// 添加故事信息
        /// </summary>
        private void AddStoryInfo()
        {
            VisualElement panInfo = new();
            VisualElement panStoryInfo = new();
            lblVarCount = new();
            lblNodeCount = new();
            lblGroupCount = new();
            lblNoteCount = new();
            lblScale = new();
            //lblMousePosition = new(GetMousePostionText());

            panStoryInfo.Add(lblVarCount);
            panStoryInfo.Add(lblNodeCount);
            panStoryInfo.Add(lblGroupCount);
            panStoryInfo.Add(lblNoteCount);
            panStoryInfo.Add(lblScale);
            //panBaseInfo.Add(lblMousePosition);

            panInfo.Add(panStoryInfo);
            Add(panInfo);

            panInfo.AddClasses("info-container");
            panStoryInfo.AddClasses("row-container");
        }

        #endregion


        #region 编辑视图元素

        /// <summary>
        /// 添加默认节点
        /// </summary>
        public void AddDefaultNodes()
        {
            CreateNode("开始", NodeType.Start, new Vector2(200, 200));
            CreateNode("结束", NodeType.End, new Vector2(800, 200));
        }

        /// <summary>
        /// 添加默认变量
        /// </summary>
        public void AddDefaultVarData()
        {
            VarData varData1 = new("变量一");
            VarData varData2 = new("变量二");
            VarData varData3 = new("变量三");
            varPanel.VarDatas.Add(varData1);
            varPanel.VarDatas.Add(varData2);
            varPanel.VarDatas.Add(varData3);
            varPanel.Draw();
        }

        /// <summary>
        /// 创建节点
        /// </summary>
        /// <param name="title">节点标题</param>
        /// <param name="type">节点类型</param>
        /// <param name="position">节点坐标</param>
        /// <param name="group">所属分组</param>
        /// <param name="shouldDraw">是否绘制</param>
        /// <returns></returns>
        public BaseNode CreateNode(string title, NodeType type, Vector2 position, Group group = null, bool shouldDraw = true)
        {
            // 获取类型
            Type nodeType = Type.GetType($"E.Story.{type}Node");

            // 创建对应节点
            BaseNode node = Activator.CreateInstance(nodeType) as BaseNode;
            node.Init(this, title, position);

            // 是否绘制
            if (shouldDraw)
            {
                node.Draw();
            }

            if (group == null)
            {
                // 加入视图
                AddElement(node);

                // 检测是否允许标题重复
                if (!StoryEditorWindow.AllowDuplicateTitles)
                    // 将此节点标记为未分组
                    AddDuplicateUngroupedNodeRecord(node);
            }
            else
            {
                // 加入分组
                group.AddElement(node);
            }

            return node;
        }

        /// <summary>
        /// 创建连线
        /// </summary>
        /// <param name="lastOutput">上行输出端口</param>
        /// <param name="nextInput">下行输入端口</param>
        /// <returns>连线</returns>
        public Edge CreateEdge(Port lastOutput, Port nextInput)
        {
            Edge edge = lastOutput.ConnectTo(nextInput);
            AddElement(edge);
            OnCreateEdge(edge);
            return edge;
        }

        /// <summary>
        /// 创建分组
        /// </summary>
        /// <param name="title">分组标题</param>
        /// <param name="position">分组坐标</param>
        /// <returns>分组</returns>
        public BaseGroup CreateGroup(string title, Vector2 position, bool moveSelectedNodes = true)
        {
            BaseGroup group = new(title, position);

            if (!StoryEditorWindow.AllowDuplicateTitles)
                AddDuplicateGroupRecord(group);

            AddElement(group);

            if (moveSelectedNodes)
            {
                // 如果选中了若干节点后创建分组，则将这些节点放入新的分组
                foreach (GraphElement item in selection)
                {
                    if (item is BaseNode baseNode)
                    {
                        group.AddElement(baseNode);
                    }
                }
            }

            return group;
        }

        /// <summary>
        /// 创建便签
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="contents">内容</param>
        /// <param name="position">坐标</param>
        /// <returns>便签</returns>
        public BaseNote CreateNote(string title, string contents, Rect layout)
        {
            BaseNote note = new(title, contents, layout);
            AddElement(note);
            return note;
        }

        /// <summary>
        /// 即将创建连线时
        /// </summary>
        /// <param name="edge">将被创建的连线</param>
        private void OnCreateEdge(Edge edge)
        {
            //Debug.Log("正在创建连线");

            // 获取连线输入端的节点（下一个节点）
            BaseNode nextNode = (BaseNode)edge.input.node;
            // 获取连线输出端的节点（上一个节点）引用的选项数据
            ChoiceData choiceData = (ChoiceData)edge.output.userData;
            // 记录下一个节点的GUID
            choiceData.NextNodeID = nextNode.GUID;
        }

        /// <summary>
        /// 即将删除节点时
        /// </summary>
        /// <param name="node">将被删除的节点</param>
        private void OnDeleteNode(BaseNode node)
        {
            //Debug.Log("正在删除节点");

            // 检测是否允许标题重复
            if (!StoryEditorWindow.AllowDuplicateTitles)
                // 从字典中移除节点
                RemoveDuplicateUngroupedNodeRecord(node);
        }

        /// <summary>
        /// 即将删除连线时
        /// </summary>
        /// <param name="edge">将被删除的连线</param>
        private void OnDeleteEdge(Edge edge)
        {
            //Debug.Log("正在删除连线");

            // 当连线的输出端口为空时，跳过
            if (edge.output == null) return;

            // 获取连线输出端的节点（上一个节点）引用的选项数据
            ChoiceData choiceData = (ChoiceData)edge.output.userData;
            // 清空记录
            choiceData.NextNodeID = "";
        }

        /// <summary>
        /// 即将删除分组时
        /// </summary>
        /// <param name="group">将被删除的分组</param>
        private void OnDeleteGroup(BaseGroup group)
        {
            //Debug.Log("正在删除分组");

            // 从字典中移除分组
            if (!StoryEditorWindow.AllowDuplicateTitles)
                RemoveDuplicateGroupRecord(group);
        }

        /// <summary>
        /// 即将删除便签时
        /// </summary>
        /// <param name="note">将被删除的便签</param>
        public void OnDeleteNote(BaseNote note)
        {
            //Debug.Log("正在删除便签");
        }

        #endregion


        #region 标题重复相关方法

        /// <summary>
        /// 向分组字典中添加分组
        /// </summary>
        /// <param name="group"></param>
        private void AddDuplicateGroupRecord(BaseGroup group)
        {
            string groupName = group.title.ToLower();

            // 如果没有同名分组，则添加一条字典记录
            if (!duplicateGroupsRecord.ContainsKey(groupName))
            {
                GroupErrorData groupErrorData = new();
                groupErrorData.Groups.Add(group);
                duplicateGroupsRecord.Add(groupName, groupErrorData);
                return;
            }

            List<BaseGroup> groupsList = duplicateGroupsRecord[groupName].Groups;

            // 加入字典
            groupsList.Add(group);

            // 设置高亮样式
            group.SetErrorStyle();

            // 将同名的另一个节点也设置高亮样式
            if (groupsList.Count == 2)
            {
                DuplicateTitlesAmount++;

                groupsList[0].SetErrorStyle();
            }
        }

        /// <summary>
        /// 从分组字典中移除分组
        /// </summary>
        /// <param name="group"></param>
        private void RemoveDuplicateGroupRecord(BaseGroup group)
        {
            string oldGroupName = group.OldTitle.ToLower();

            List<BaseGroup> groupsList = duplicateGroupsRecord[oldGroupName].Groups;

            // 移出字典
            groupsList.Remove(group);

            // 重置样式
            group.ResetStyle();

            // 将原本同名的另一个分组也重置样式
            if (groupsList.Count == 1)
            {
                DuplicateTitlesAmount--;

                groupsList[0].ResetStyle();
                return;
            }

            // 如果同名分组都已不存在，则移除该字典记录
            if (groupsList.Count == 0)
            {
                duplicateGroupsRecord.Remove(oldGroupName);
            }
        }

        /// <summary>
        /// 向未分组节点字典中添加节点
        /// </summary>
        /// <param name="node"></param>
        public void AddDuplicateUngroupedNodeRecord(BaseNode node)
        {
            string nodeName = node.Title.ToLower();

            // 如果没有同名节点，则添加一条字典记录
            if (!duplicateUngroupedNodesRecord.ContainsKey(nodeName))
            {
                NodeErrorData nodeErrorData = new();
                nodeErrorData.Nodes.Add(node);
                duplicateUngroupedNodesRecord.Add(nodeName, nodeErrorData);
                return;
            }

            List<BaseNode> ungroupedNodes = duplicateUngroupedNodesRecord[nodeName].Nodes;

            // 加入字典
            ungroupedNodes.Add(node);

            // 设置高亮样式
            node.SetErrorStyle();

            // 将同名的另一个节点也设置高亮样式
            if (ungroupedNodes.Count == 2)
            {
                DuplicateTitlesAmount++;

                ungroupedNodes[0].SetErrorStyle();
            }
        }

        /// <summary>
        /// 从未分组节点字典中移除节点
        /// </summary>
        /// <param name="node">目标节点</param>
        public void RemoveDuplicateUngroupedNodeRecord(BaseNode node)
        {
            string nodeName = node.Title.ToLower();

            List<BaseNode> ungroupedNodesList = duplicateUngroupedNodesRecord[nodeName].Nodes;

            // 移出字典
            ungroupedNodesList.Remove(node);

            // 重置样式
            node.ResetStyle();

            // 将原本同名的另一个节点也重置样式
            if (ungroupedNodesList.Count == 1)
            {
                DuplicateTitlesAmount--;

                ungroupedNodesList[0].ResetStyle();
                return;
            }

            // 如果同名节点都已不存在，则移除该字典记录
            if (ungroupedNodesList.Count == 0)
            {
                duplicateUngroupedNodesRecord.Remove(nodeName);
            }
        }

        /// <summary>
        /// 向已分组节点字典中添加节点
        /// </summary>
        /// <param name="node">目标节点</param>
        /// <param name="group">目标分组</param>
        public void AddDuplicateGroupedNodeRecord(BaseNode node, BaseGroup group)
        {
            string nodeName = node.Title.ToLower();

            // 如果字典中不存在此分组，则添加一条分组记录
            if (!duplicateGroupedNodesRecord.ContainsKey(group))
            {
                duplicateGroupedNodesRecord.Add(group, new());
            }

            // 如果没有同名节点，则添加一条字典记录
            if (!duplicateGroupedNodesRecord[group].ContainsKey(nodeName))
            {
                NodeErrorData nodeErrorData = new();
                nodeErrorData.Nodes.Add(node);
                duplicateGroupedNodesRecord[group].Add(nodeName, nodeErrorData);
                return;
            }

            List<BaseNode> groupedNodesList = duplicateGroupedNodesRecord[group][nodeName].Nodes;

            // 加入字典
            groupedNodesList.Add(node);

            // 设置高亮样式
            node.SetErrorStyle();

            // 将同名的另一个节点也设置高亮样式
            if (groupedNodesList.Count == 2)
            {
                DuplicateTitlesAmount++;

                groupedNodesList[0].SetErrorStyle();
            }
        }

        /// <summary>
        /// 从已分组节点字典中移除节点
        /// </summary>
        /// <param name="node">目标节点</param>
        /// <param name="group">目标分组</param>
        public void RemoveDuplicateGroupedNodeRecord(BaseNode node, BaseGroup group)
        {
            string nodeName = node.Title.ToLower();

            List<BaseNode> groupedNodesList = duplicateGroupedNodesRecord[group][nodeName].Nodes;

            // 移出字典
            groupedNodesList.Remove(node);

            // 重置样式
            node.ResetStyle();

            // 将原本同名的另一个节点也重置样式
            if (groupedNodesList.Count == 1)
            {
                DuplicateTitlesAmount--;

                groupedNodesList[0].ResetStyle();
                return;
            }

            // 如果同名节点都已不存在，则移除该分组记录
            if (groupedNodesList.Count == 0)
            {
                duplicateGroupedNodesRecord[group].Remove(nodeName);

                // 如果同名分组都已不存在，则移除该字典记录
                if (duplicateGroupedNodesRecord[group].Count == 0)
                {
                    duplicateGroupedNodesRecord.Remove(group);
                }
            }

        }

        #endregion


        #region 实用方法

        /// <summary>
        /// 将节点插入连线
        /// </summary>
        /// <param name="node"></param>
        /// <param name="edge"></param>
        public void InsertNodeToEdge(BaseNode node, Edge edge)
        {
            // 获取原端口
            Port lastOutput = edge.output;
            Port nextInput = edge.input;

            // 删除原连线
            DeleteElements(new List<Edge>() { edge });

            // 创建左侧连线
            CreateEdge(lastOutput, node.Input);

            // 创建右侧连线
            if (node.Output != null)
            {
                CreateEdge(node.Output, nextInput);
            }
        }

        /// <summary>
        /// 获取结束节点数量
        /// </summary>
        /// <returns>结束节点数量</returns>
        private int GetEndNodesAmount()
        {
            return graphElements.Where(e => e is EndNode).ToList().Count;
        }

        /// <summary>
        /// 获取本地光标坐标
        /// </summary>
        /// <param name="screenMousePosition">屏幕光标坐标</param>
        /// <param name="isNodeCreationBox">是否是添加节点对话框</param>
        /// <returns>本地光标坐标</returns>
        public Vector2 GetLocalMousePosition(Vector2 screenMousePosition, bool isNodeCreationBox = false)
        {
            Vector2 windowMousePosition;
            if (isNodeCreationBox)
            {
                // 将光标的屏幕坐标转换为光标在当前窗口内的坐标
                windowMousePosition = screenMousePosition - storyEditorWindow.position.position;
            }
            else
            {
                windowMousePosition = screenMousePosition;
            }
            // 将光标在当前窗口内的坐标转换为光标在节点视图内的坐标
            Vector2 localMousePosition = contentViewContainer.WorldToLocal(windowMousePosition);
            return localMousePosition;
        }

        /// <summary>
        /// 清除视图
        /// </summary>
        public void ClearGraph()
        {
            graphElements.ForEach(e => RemoveElement(e));

            duplicateGroupsRecord.Clear();
            duplicateGroupedNodesRecord.Clear();
            duplicateUngroupedNodesRecord.Clear();

            DuplicateTitlesAmount = 0;

            varPanel.ClearPanel();
        }

        /// <summary>
        /// 切换小地图
        /// </summary>
        public void ToggleMiniMap()
        {
            navMap.visible = !navMap.visible;
        }

        /// <summary>
        /// 切换变量面板
        /// </summary>
        public void ToggleVarPanel()
        {
            varPanel.visible = !varPanel.visible;
        }

        /// <summary>
        /// 当变量数据更新时，更新视图
        /// </summary>
        public void OnEditVarDatas()
        {
            // 获取需要重绘的节点
            List<BaseNode> nodesToReRraw = new();
            nodes.ForEach(node =>
            {
                if (node is EditVarNode || node is BranchNode)
                {
                    nodesToReRraw.Add((BaseNode)node);
                    return;
                }
            });

            // 重绘节点
            foreach (BaseNode node in nodesToReRraw)
            {
                node.DrawExtensionContainer();
            }
        }

        /// <summary>
        /// 获取鼠标坐标文本
        /// </summary>
        /// <returns>鼠标坐标文本</returns>
        //private string GetMousePostionText()
        //{
        //    Vector2 mousePos = GetLocalMousePosition();
        //    int x = (int)mousePos.x;
        //    int y = (int)mousePos.y;
        //    return $"({x},{y})";
        //}

        /// <summary>
        /// 更新故事信息
        /// </summary>
        public void UpdateStoryInfo()
        {
            UpdateVarCountInfo();
            UpdateNodeCountInfo();
            UpdateGroupCountInfo(); 
            UpdateNoteCountInfo();
            UpdateScaleInfo();
        }

        /// <summary>
        /// 更新变量数量信息
        /// </summary>
        private void UpdateVarCountInfo()
        {
            lblVarCount.text = varPanel.VarDatas.Count + "变量";
        }

        /// <summary>
        /// 更新节点数量信息
        /// </summary>
        private void UpdateNodeCountInfo()
        {
            //int count = 0;
            //graphElements.ForEach(element =>
            //{
            //    if (element is BaseNode node)
            //    {
            //        count++;
            //        return;
            //    }
            //});
            //return count + "节点";
            lblNodeCount.text = nodes.Count() + "节点";
        }

        /// <summary>
        /// 更新分组数量信息
        /// </summary>
        private void UpdateGroupCountInfo()
        {
            int count = 0;
            graphElements.ForEach(element =>
            {
                if (element is BaseGroup group)
                {
                    count++;
                    return;
                }
            });
            lblGroupCount.text = count + "分组";
        }

        /// <summary>
        /// 更新便签数量信息
        /// </summary>
        private void UpdateNoteCountInfo()
        {
            int count = 0;
            graphElements.ForEach(element =>
            {
                if (element is BaseNote note)
                {
                    count++;
                    return;
                }
            });
            lblNoteCount.text = count + "便签";
        }

        /// <summary>
        /// 更新缩放信息
        /// </summary>
        private void UpdateScaleInfo()
        {
            lblScale.text = string.Format("{0:F2}", scale) + "x";
        }

        #endregion
    }
}